<template>
    <!-- 搜索 -->
    <label>
        根据姓名搜索:
    </label>
    <el-select @clear="clearSearchKey" clearable @change="searchChange" v-model="searchKey" filterable remote
        placeholder="🔍请输入姓名搜索" :remote-method="remoteMethod" :loading="searchLoading">
        <el-option v-for="item in searchOptions" :key="item.value" :label="item.label" :value="item.value" />
    </el-select>
    <br>
    <br>
    <!-- 按钮 -->
    <el-button :icon="Plus" type="primary" @click="addStu">添加项目</el-button>
    <br>
    <br>
    <div class="export">
        <el-button @click="exportExcel">
            <template #icon>
                <svg>
                    <use class="icon" xlink:href="#icon-excel-"></use>
                </svg>
            </template>
            <template #default>
                导出Excel
            </template>
        </el-button>
    </div>
    <!-- 表格 -->
    <el-table v-loading="tableLoading" :data="tableData" border style="width: 100%">
        <el-table-column prop="headimgurl" label="头像" width="140">
            <template v-slot="{ row }">
                <el-avatar size="large" shape="square" :src="row.headimgurl"></el-avatar>
            </template>
        </el-table-column>
        <el-table-column prop="name" label="姓名" />
        <el-table-column prop="degree" label="学历" />
        <el-table-column prop="class" label="班级" />
        <el-table-column prop="productUrl" label="项目" />
        <el-table-column prop="cTime" label="创建时间" />
        <el-table-column prop="address" label="操作">
            <template v-slot="{ row }">
                <el-button type="success" circle :icon="View" />
                <el-button type="primary" circle :icon="Edit" @click="edit(row)" />
                <el-button type="danger" circle :icon="Delete" @click="del(row)" />
            </template>
        </el-table-column>
    </el-table>
    <!-- 分页 -->
    <br>
    <div class="box">
        <el-pagination @current-change="pageChange" background layout="prev, pager, next" :total="total" />
    </div>
    <!-- dialog弹窗组件 -->
    <qfDialog :dialogFormData="dialogFormData" @validateSuccess="dialogFormValidateSuccess" @dialogCancel="dialogCancel"
        :visible="dialogVisible" @closed="close" :title="dialogTitle">
        <template v-slot:upload>
            <el-upload v-loading="uploadLoading" class="avatar-uploader" method="post" name="headimgurl"
                action="/api/students/uploadStuAvatar" :show-file-list="false" :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload">
                <img v-if="imageUrl" :src="imageUrl" class="avatar" />
                <el-icon v-else class="avatar-uploader-icon">
                    <Plus />
                </el-icon>
            </el-upload>
        </template>
    </qfDialog>
</template>

<script setup>
import qfDialog from "@/components/dialog/index.vue"
import { ref, reactive, onMounted } from "vue"
//引入请求数据的方法
import * as api from "@/api/stu"
import { ElMessage, ElMessageBox } from "element-plus";
//引入图标
import {
    View,
    Delete,
    Edit,
    Plus
} from '@element-plus/icons-vue'
//引入导出excel的插件
import cc from "qf-export-excel"
//搜索逻辑
//搜索的数据及其结构
let searchOptions = ref([])
//搜索关键字
let searchKey = ref("")
//搜索的加载动画
let searchLoading = ref(false)
//搜索框输入之后会触发的方法,这里负责承呈现搜索的联想数据
let remoteMethod = async (currentKeyWord) => {
    if (!currentKeyWord) {
        return
    }
    //打开表格的loading动画
    searchLoading.value = true
    //这个三元的目的是为了用户在输入或者在选择的时候都能获取到搜索的关键字
    // let key = searchKey.value ? searchKey.value : currentKeyWord
    // console.log(key);
    try {
        //要搜索全部的数据，所以传递空字符串count，默认搜索全部
        let res = await api.searchStuListApi(currentKeyWord, "")
        //给联想的列表进行赋值
        let repeatDatas = searchOptions.value = res.data.data.map(item => ({ value: item.name }))
        //要去重操作
        let norepeatDatas = [];
        for (var i = 0; i < repeatDatas.length; i++) {
            //声明一个开关
            let flag = true
            for (var j = 0; j < norepeatDatas.length; j++) {
                if (repeatDatas[i].value === norepeatDatas[j].value) {
                    flag = false
                    break;
                }
            }
            if (flag) {
                norepeatDatas.unshift(repeatDatas[i])
            }
        }
        //去重后对options进行赋值操作

        searchOptions.value = norepeatDatas
        console.log(searchOptions.value);
        //关闭表格的loading动画
        searchLoading.value = false
    } catch (e) {
        console.log(e);
        searchLoading.value = false
    }
}

//清空关键字之后的方法
let clearSearchKey = () => {
    //初始化数据，让页码重新回到第一页
    currentPage.value = 1
}

//用户选择了输入框的值之后，负责更新表格的数据
let searchChange = async (key, page = 1, count = 10) => {
    //获取用户点选的值
    //打开表格的loading动画
    tableLoading.value = true
    //清空上次获取到的选项
    searchOptions.value = []
    try {
        let res = await api.searchStuListApi(searchKey.value, count, page)
        //对表格数据的操作，将搜索的结果赋值给表格
        tableData.value = res.data.data
        tableLoading.value = false
        //对搜索的结果进行分页
        setPageNation(res.data.total)
    } catch (e) {
        console.log(e);
        tableLoading.value = false
    }
}

//列表逻辑
//表格的数据
let tableData = ref([])

//加载动画
let tableLoading = ref(true)
//封装一个方法，专门用于获取表格数据
let getStulist = async (page, count, classes) => {
    //开启加载动画
    tableLoading.value = true
    try {
        let res = await api.getStuListApi(page, count, classes)
        tableData.value = res.data.data
        tableLoading.value = false
        //设置分页器的数量
        setPageNation(res.data.total)
    } catch (e) {
        console.log(e);
        //关闭加载动画
        tableLoading.value = false
    }
}

//处理分页
//分页器的total属性
let total = ref(1)
// 一页展示多少条
let pageSize = ref(10)
//页码变更的时候
let currentPage = ref(1)
let pageChange = (inputCurrentPage) => {
    //动态变更页码
    currentPage.value = inputCurrentPage
    //判断有没有搜索关键字,如果有那么应该更新搜索的分页结果
    if (searchKey.value) {
        searchChange(null, inputCurrentPage)
    } else {
        //页码切换，重新拉取列表
        getStulist(inputCurrentPage)
    }
    //console.log(current)
    //console.log(currentPage)
}

//专门修改分页器内容的方法
let setPageNation = (totalCount = 10, count = 10, currentPage = 1) => {
    total.value = totalCount
    pageSize.value = count
}

//添加stu信息
//声明dialogVisible控制dialog
//dialog标题
let dialogTitle = ref('增加学员数据')
let dialogVisible = ref(false)
let addStu = () => {
    //打开dialog
    dialogVisible.value = true
    dialogTitle.value = '增加学员数据'
}

//dialog的数据源
let dialogFormData = reactive({
    class: {
        label: '班级',
        value: ''
    },
    name: {
        label: '姓名',
        value: ''
    },
    age: {
        label: '年龄',
        value: ''
    },
    city: {
        label: '城市',
        value: ''
    },
    degree: {
        label: '学历',
        value: ''
    },
    productUrl: {
        label: '项目地址',
        value: ''
    },
    description: {
        label: '描述',
        value: ''
    }
})

//dialog点击了确定按钮，并且表单校验通过触发的逻辑
let dialogFormValidateSuccess = async (form) => {
    //发起请求，将输入的内容传递给服务器
    let message = '添加成功'
    let params = {
        headimgurl: '',
        class: dialogFormData.class.value,
        name: dialogFormData.name.value,
        age: dialogFormData.age.value,
        city: dialogFormData.city.value,
        degree: dialogFormData.degree.value,
        productUrl: dialogFormData.productUrl.value,
        description: dialogFormData.description.value,
    }
    try {
        let apiMethod = null
        switch (dialogTitle.value) {
            case '增加学员数据':
                apiMethod = api.addStuApi
                //删除sId属性
                params.sId ? delete params.sId : ""
                break
            case '编辑数据':
                apiMethod = api.updateStuApi
                //给params添加sId属性
                params.sId = sId.value
                //更改提示信息
                message = '修改成功'
        }
        //判断是否上传头像，如果上传了，那么携带到params中去
        params.headimgurl = headimgurl.value ? headimgurl.value : ""
        let res = await apiMethod(params)
        //根据dialogTitle来区分要发送编辑请求还是发送增加请求
        //添加成功
        //1.提示添加成功
        ElMessage({
            type: 'success',
            message
        })
        //2.关掉dialog
        dialogVisible.value = false
        //3.清空表单
        form.value.resetFields()
        //4.更新列表
        getStulist()
    } catch (e) {
        ElMessage({
            type: 'error',
            message: e.toString()
        })
        console.log(e);
    }
}

//点击dialog取消按钮触发逻辑
let dialogCancel = () => {
    dialogVisible.value = false
}

//dialog关闭之后，要同步控制关闭属性的值
//这么做的目的是为了处理点击空白区域或者右上角叉叉的时候，造成后续dialog不能弹出的情况
let close = () => {
    dialogVisible.value = false
    //将数据清空
    let keys = Object.keys(dialogFormData)
    keys.forEach(key => {
        dialogFormData[key].value = ""
    })
    //清空头像的回显
    imageUrl.value = ''
}


//编辑
//声明一个变量，存储sId，便于编辑的时候传递给后端
let sId = ref("")
let edit = (row) => {
    //1.打开dialog
    dialogVisible.value = true
    //2.修改标题
    dialogTitle.value = '编辑数据'
    //3.数据需要回显
    let keys = Object.keys(dialogFormData)
    keys.forEach(key => {
        dialogFormData[key].value = row[key]
    })
    //给sId赋值
    sId.value = row.sId
    //更改全局的headimgurl这个字段，便于数据的传递
    headimgurl.value = row.headimgurl
    //回显
    imageUrl.value = row.headimgurl
}

//删除
let del = (row) => {
    //获取当前这条数据的id，传递给后台就可以了
    //1.交互，让用户确认是否删除
    ElMessageBox.confirm('此操作将永久删除 ' + row.name + ', 是否继续?', '删除提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'

    })
        .then(async () => {
            //2.发请求，删除数据
            try {
                let res = await api.delStuApi(row.sId)
                ElMessage({
                    type: 'success',
                    message: '删除成功'
                })
                //更新列表
                getStulist()
            } catch (e) {
                ElMessage({
                    type: 'error',
                    message: e.toString()
                })
            }
        })
        .catch(() => {
            ElMessage({
                type: 'warning',
                message: '已取消删除'
            })
        })
    //
}

//导出Excel

let exportExcel = () => {
    //定义表头
    let titleSource = [
        {
            title: "姓名",
            key: "name"
        },
        {
            title: "年龄",
            key: "age"
        },
        {
            title: "头像地址",
            key: "headimgurl"
        },
        {
            title: "学历",
            key: "degree"
        },
        {
            title: "班级",
            key: "class"
        },
    ]
    cc(titleSource, tableData.value, '扛米大队')
}












//上传文件
//一个保存上传地址的变量
let imageUrl = ref()
//声明一个headimgurl变量，用于将参数在表单dialog通过的时候，一并提交给后台
let headimgurl = ref()
//加载动画
let uploadLoading = ref(false)
//上传成功的方法
let handleAvatarSuccess = (res, uploadFile) => {
    if (res.state) {
        //头像上传成功
        ElMessage({
            type: 'success',
            message: res.msg
        })
        headimgurl.value = res.headimgurl
    } else {
        ElMessage({
            type: 'error',
            message: res.msg
        })
    }
    //关闭loading动画
    uploadLoading.value = false
    imageUrl.value = URL.createObjectURL(uploadFile.raw)
}
//上传之前
let beforeAvatarUpload = (rawFile) => {
    //允许上传文件的类型
    let acceptType = ['image/jpeg', 'image/png']
    //判断当前上传的文件是否包含在上面的数组中
    let isAccept = acceptType.includes(rawFile.type)
    if (!isAccept) {
        ElMessage.error('上传的文件类型只能是jpeg或者是png,您当前上传的文件类型是' + rawFile.type)
        return false
    } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error('上传的文件大小不能超过1M')
        return false
    }
    //打开加载动画
    uploadLoading.value = true
    return true
}


onMounted(() => {
    getStulist()
})
</script>


<script>
export default {
    meta: {
        name: "学员项目管理",
        title: "xyxmgl",
        icon: 'icon-chanpin'
    }
}
</script>

<style scoped>
.box {
    width: 400px;
    height: 32px;
    margin: 0 auto;
}

.avatar-uploader .avatar {
    width: 178px;
    height: 178px;
    display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
    border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
}
</style>